//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include <aura.h>
//BUGBUG:If there is elf wchar_t must be changed
EXTERN_C Aura_ECode CDECL CentralInitialize();
EXTERN_C void  CDECL CentralDestroy();
EXTERN_C void  CDECL CentralOnRunning();

EXTERN_C void CDECL exit(int);
EXTERN_C int CDECL isdigit(int);
EXTERN_C int CDECL _wtoi(const wchar_t * string);
EXTERN_C wchar_t* CDECL wcscat(wchar_t*, const wchar_t*);

EXTERN_C wchar_t* STDCALL GetCommandLineW(void);
EXTERN_C wchar_t** STDCALL CommandLineToArgvW(const wchar_t*,int*);

typedef struct _SECURITY_ATTRIBUTES {
  unsigned long  nLength;
  void * lpSecurityDescriptor;
  int   bInheritHandle;
} * LPSECURITY_ATTRIBUTES;

EXTERN_C void * STDCALL CreateEventW(LPSECURITY_ATTRIBUTES,int, int, const wchar_t *);
EXTERN_C unsigned long STDCALL WaitForSingleObjectEx(void*, unsigned long, int);
EXTERN_C int STDCALL PulseEvent(void *);

int debug_level = 0;
wchar_t exeName[AURA_MAX_PATH];
wchar_t exeArgs[AURA_MAX_PATH];

static void usage(void)
{
    Aura_printf("\nusage: ElCentral [options] filename [args...]\n\n");
    Aura_printf("options:\n");
    Aura_printf("   -d<n>  set debug level to <n>\n");
    Aura_printf("   -h     display this help message\n");
    Aura_printf("   -v     display verbose information and exit\n");
    Aura_printf("\n");
}

static void parse_args()
{
    wchar_t *pCmdLine, ** wargv;
    int argc;

    pCmdLine = GetCommandLineW();
    wargv = (wchar_t**) CommandLineToArgvW (pCmdLine, &argc);

    for (int i = 1; i < argc; i++) {
        if (wargv[i][0] == L'-' && exeName[0] == L'\0') {

            switch (wargv[i][1]) {
                case 'd':
                    if (isdigit(wargv[i][2]))
                        debug_level = _wtoi( wargv[i] + 2 );
                    else
                        debug_level++;
                    break;
                case 'v':
                    debug_level++;
                    break;
                case 'h':
                    usage();
                    exit(0);
                    break;
                default:
                    Aura_printf("ElAura: unknown option '%S'\n", wargv[i] );
                    usage();
                    exit(1);
            }
        }
        else {
            if (exeName[0] == L'\0') {
                wcscat(exeName, wargv[i]);
            }
            else {
                wcscat(exeArgs, wargv[i]);
                wcscat(exeArgs, L" ");
            }
        }
    }
}

EXTERN_C void ExitingThread(Aura_PVoid arg)
{
    // elaura.exe will send event to notify server to exit!
    void * hExitPALServerEvent;
    //BUGBUG:These windows function must be out of here!!
    hExitPALServerEvent = CreateEventW(0, 0, 0, L"ExitElCentral");
    assert(0 != hExitPALServerEvent);

    WaitForSingleObjectEx(hExitPALServerEvent, (unsigned long)-1, 0);
    AuraProcess_Exit(0);
}

int main(int argc, char **argv)
{

    Aura_ECode ec = AURA_NOERROR;
    parse_args();

    ////Aura_printf("[<ElAura>] ElCentral Startup ...\n\n");

    ec = CentralInitialize();
    if (AURA_FAILED(ec)) {
        Aura_printf("[<ElAura>] ElCentral Startup Failed, ec:0x%08x\n",ec);
        return -1;
    }

//only for elaura.exe, should be removed in the future
//*******************************************
    void * hPalServerStartedEvent;
    hPalServerStartedEvent = CreateEventW(0, 0, 0, L"ElCentralStarted");
    PulseEvent(hPalServerStartedEvent);

    Aura_ThreadId dwExitingThreadId;
    Aura_Handle hExitingThread;
    ec = AuraThread_Create(
                ExitingThread,
                AURA_NULL,              // thread parameter
                0,                      // not suspended
                &hExitingThread,
                &dwExitingThreadId);    // returns thread ID

    if (AURA_FAILED(ec))
    {
        Aura_printf("Failed to create exiting thread for server.\n");
        return 1;
    }
    else
        AuraThread_Destroy(hExitingThread);
//********************************************

    CentralOnRunning();

    //Aura_printf("[<ElAura>] ElCentral Shutdown ...\n");
    CentralDestroy();

    return 0;
}

#include <elastos.h>
EXTERN_C Elastos::ECode /* IApplet* */ __stdcall CrtGetCurrentAppletDir(Elastos::WStringBuf* pwsAppletDir)
{
    return E_NOT_IMPLEMENTED;
}

